<?php
namespace xptml;

abstract class Application
{
	// Inherited Constants
	const xptml_version = 0.1;

	// Private Properties
	private static $instance = null;
	private $GUID = null;
	private $Cache = null;

	// Protected Properties
	protected $WEBROOT = null;
	protected $URI = null;
	protected $Config = null;

	// Abstract Methods
	abstract protected function construct($param);
	abstract protected function destruct();

	// Final Methods
	final private function __construct($param)
	{
		// Load configuration
		$this->Config = array_merge(require_once(XPTMLROOT . 'config.php'), parse_ini_file(DOCROOT . 'site/config.ini', true));

		// Generate a Globally Unique ID to identify this application in shared folder structures
		$this->GUID = md5($this->Config['application']['name'] . self::xptml_version);

		// Get cache path, and create if doesn't already exist
		$this->Cache = $this->getCache();

		// Set default TimeZone
		date_default_timezone_set($this->Config['application']['timezone']);

		// Get the WEBROOT and URI
		{
            if (! isset($_SERVER['REDIRECT_URL'])) list($_SERVER['REDIRECT_URL']) = explode ('?', $_SERVER['REQUEST_URI']);
			$url = explode('/', substr($_SERVER['REDIRECT_URL'], -1) == '/' ? $_SERVER['REDIRECT_URL'] : dirname($_SERVER['REDIRECT_URL']));
			$reference = explode('/', dirname($_SERVER['SCRIPT_FILENAME']));
			$base = array_intersect($url, $reference);

			$this->WEBROOT = (isset($_SERVER['HTTPS']) ? 'https' : 'http') . "://{$_SERVER['HTTP_HOST']}" . rtrim(implode('/', $base), '/') . '/';
			$this->URI = implode('/', array_diff(explode('/', $_SERVER['REDIRECT_URL']), $base));

			unset($url, $base, $reference);
		}

		return static::construct($param);
	}

	final public function __destruct()
	{
		static::destruct();
	}

	final static function start($param = array())
	{
		if (!is_null(self::$instance))
		{
			throw new \LogicException('Application is already started');
		}

		return self::$instance = new static($param);
	}

	final static function get()
	{
		return self::$instance;
	}

	// Overloadable Methods
	public function getWebRoot()
	{
		return $this->WEBROOT;
	}

	public function getURI()
	{
		return $this->URI;
	}

	public function getGUID()
	{
		return $this->GUID;
	}

	public function getCache($directory = '')
	{
		static $Cache = null;
		if (is_null($Cache)) $Cache = $this->Config['application']['cache'] . $this->GUID;
		if (! file_exists($path = "{$Cache}/{$directory}")) mkdir($path, 0770, true);
		return realpath($path) . '/';
	}
}

?>